﻿using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Security.Principal;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing;
using System.Web.Security;
using CarHelpDesk.Web.Models;
using CarHelpDesk.Web.Models.Repositories.LinqRepositories;
using CarHelpDesk.Web.Models.Repositories;
using System.ComponentModel.DataAnnotations;

namespace CarHelpDesk.Web.Controllers
{

    [HandleError]
    public class AccountController : Controller
    {
        private IUserDetailsRepository repo;
        public AccountController()
        {
            repo = new CarHelpDesk.Web.Models.Repositories.LinqRepositories.UserDetailsRepository();
        }

        public AccountController(IUserDetailsRepository aRepository)
        {
            repo = aRepository;
        }

        public IFormsAuthenticationService FormsService { get; set; }
        public IMembershipService MembershipService { get; set; }

        protected override void Initialize(RequestContext requestContext)
        {
            if (FormsService == null) { FormsService = new FormsAuthenticationService(); }
            if (MembershipService == null) { MembershipService = new AccountMembershipService(); }

            base.Initialize(requestContext);
        }

        // **************************************
        // URL: /Account/LogOn
        // **************************************

        public ActionResult LogOn()
        {
            return View();
        }

        [HttpPost]
        public ActionResult LogOn(LogOnModel model, string returnUrl)
        {
            if (ModelState.IsValid)
            {
                if (MembershipService.ValidateUser(model.UserName, model.Password))
                {
                    FormsService.SignIn(model.UserName, model.RememberMe);

                    if (!String.IsNullOrEmpty(returnUrl))
                    {
                        return Redirect(returnUrl);
                    }
                    else
                    {
                        return RedirectToAction("Index", "Home");
                    }
                }
                else
                {
                    ModelState.AddModelError("", "The user name or password provided is incorrect.");
                }
            }

            // If we got this far, something failed, redisplay form
            return View(model);
        }

        // **************************************
        // URL: /Account/LogonOrRegister
        // **************************************

        public ActionResult LogonOrRegister()
        {
            return PartialView();
        }

        [HttpPost]
        public ActionResult LogonOrRegister(LogonOrRegisterModel model)
        {
            this.ValidateLogonOrRegisterModel(model);

            model.LogonOrRegisterSuccessful = false;
            if (ModelState.IsValid)
            {
                if (model.LogonOrRegisterAction == "logon")
                {
                    LogonInternal(model);
                }
                else if (model.LogonOrRegisterAction == "register")
                {
                    RegisterInternal(model);
                }
            }

            ViewData["PasswordLength"] = MembershipService.MinPasswordLength;
            return PartialView(model);
        }

        private void LogonInternal(LogonOrRegisterModel model)
        {
            if (MembershipService.ValidateUser(model.UserName, model.Password))
            {
                FormsService.SignIn(model.UserName, model.RememberMe);
                model.LogonOrRegisterSuccessful = true;
            }
            else
            {
                ModelState.AddModelError("", "The user name or password provided is incorrect.");
            }
        }

        private void RegisterInternal(LogonOrRegisterModel model)
        {
            // Attempt to register the user
            MembershipCreateStatus createStatus = MembershipService.CreateUser(model.UserName, model.Password, model.Email);

            if (createStatus == MembershipCreateStatus.Success)
            {
                UserDetail newUserDetails = new UserDetail();
                newUserDetails.UserID = (Guid)Membership.GetUser(model.UserName).ProviderUserKey;
                newUserDetails.UserRating = 0;
                newUserDetails.UpdateDate = DateTime.Now;
                repo.addUserDetail(newUserDetails);

                FormsService.SignIn(model.UserName, false /* createPersistentCookie */);
                model.LogonOrRegisterSuccessful = true;
                //return RedirectToAction("Index", "Home");
            }
            else
            {
                ModelState.AddModelError("", AccountValidation.ErrorCodeToString(createStatus));
            }

        }

        private void ValidateLogonOrRegisterModel(LogonOrRegisterModel model)
        {
            if (model.LogonOrRegisterAction == "register")
            {
                if (model.Password != model.ConfirmPassword)
                {
                    ModelState.AddModelError("", "The password and confirmation password do not match.");
                }
            }
            else if (model.LogonOrRegisterAction == "logon")
            {
                ModelState["Email"].Errors.Clear();
                ModelState["ConfirmPassword"].Errors.Clear();                
            }
            else
            {
                ModelState.AddModelError("", "Unknown action");
            }
        }

        // **************************************
        // URL: /Account/LogOff
        // **************************************

        public ActionResult LogOff()
        {
            FormsService.SignOut();

            return RedirectToAction("Index", "Home");
        }

        // **************************************
        // URL: /Account/AccountView
        // **************************************

        public ActionResult AccountView()
        {
            Guid UserID = this.GetCurrentUserID();

            AccountViewModel model = new AccountViewModel();
            model.UserName = Membership.GetUser().UserName;
            model.Email = Membership.GetUser().Email;
            model.UserDetail = repo.getUserDetailByGuid(UserID);            

            return View("AccountView", model);
        }

        // **************************************
        // URL: /Account/AccountEdit
        // **************************************

        public ActionResult AccountEdit()
        {
            AccountEditModel model = new AccountEditModel();
            model.Email = Membership.GetUser().Email;
            model.UserDetail = repo.getUserDetailByGuid(this.GetCurrentUserID());
            return View("AccountEdit", model);
        }

        [HttpPost]
        public ActionResult AccountEdit(AccountEditModel model)
        {
            RegisterModel regModel = new RegisterModel();
            if (ModelState.IsValid)
            {
                model.Email = Request.Form["Email"];
                MembershipService.UpdateUser(model);
                regModel.UserName = Membership.GetUser().UserName;
                regModel.Email = model.Email;

#warning: try to make direct update
                UserDetail oldDetails = repo.getUserDetailByGuid(this.GetCurrentUserID());

                oldDetails.FirstName = model.UserDetail.FirstName;
                oldDetails.LastName = model.UserDetail.LastName;

                repo.updateUserDetail(oldDetails);

                return RedirectToAction("AccountView");
            }
            return View(model);
        }

        // **************************************
        // URL: /Account/Register
        // **************************************

        public ActionResult Register()
        {
            ViewData["PasswordLength"] = MembershipService.MinPasswordLength;
            return View();
        }

        [HttpPost]
        public ActionResult Register(RegisterModel model)
        {
            if (ModelState.IsValid)
            {
                // Attempt to register the user
                MembershipCreateStatus createStatus = MembershipService.CreateUser(model.UserName, model.Password, model.Email);

                if (createStatus == MembershipCreateStatus.Success)
                {

                    UserDetail newUserDetails = new UserDetail();
                    newUserDetails.UserID = (Guid)Membership.GetUser(model.UserName).ProviderUserKey;
                    newUserDetails.UserRating = 0;
                    newUserDetails.UpdateDate = DateTime.Now;
                    repo.addUserDetail(newUserDetails);

                    FormsService.SignIn(model.UserName, false /* createPersistentCookie */);
                    return RedirectToAction("Index", "Home");
                }
                else
                {
                    ModelState.AddModelError("", AccountValidation.ErrorCodeToString(createStatus));
                }
            }

            // If we got this far, something failed, redisplay form
            ViewData["PasswordLength"] = MembershipService.MinPasswordLength;
            return View(model);
        }

        // **************************************
        // URL: /Account/ChangePassword
        // **************************************

        [Authorize]
        public ActionResult ChangePassword()
        {
            ViewData["PasswordLength"] = MembershipService.MinPasswordLength;
            return View();
        }

        [Authorize]
        [HttpPost]
        public ActionResult ChangePassword(ChangePasswordModel model)
        {
            if (ModelState.IsValid)
            {
                if (MembershipService.ChangePassword(User.Identity.Name, model.OldPassword, model.NewPassword))
                {
                    return RedirectToAction("ChangePasswordSuccess");
                }
                else
                {
                    ModelState.AddModelError("", "The current password is incorrect or the new password is invalid.");
                }
            }

            // If we got this far, something failed, redisplay form
            ViewData["PasswordLength"] = MembershipService.MinPasswordLength;
            return View(model);
        }

        // **************************************
        // URL: /Account/ChangePasswordSuccess
        // **************************************

        public ActionResult ChangePasswordSuccess()
        {
            return View();
        }

    }
}
